import * as XLSX from 'xlsx'
import * as  XLSX2 from 'xlsx-style';
import $ from 'jquery'
export function sheet2Excel({ fileName, tH_data, tB_data, merge, mergeProp } = {}) {
    console.log(tB_data, 'tB_data');
    const str = '<table>' + createTable(tH_data, tB_data, fileName, merge, mergeProp) + '</table>'
    const th_length = $(str).eq(0).find('thead tr').length, ths = $(str).eq(0).find('thead tr').eq(th_length - 1).find('td')
    const sheet = XLSX.utils.table_to_sheet($($(str))[0]);
    for (let key in sheet) {
        if (key === '!cols') {
            sheet[key] = []
            console.log(ths, 'ths', $($(str))[0]);
            Array.from(ths).forEach(td => {
                console.log(td, $(td).attr('width'));
                sheet[key].push({ wpx: $(td).attr('width') })
            })
        }
        if (key.indexOf('!') !== 0) {
            const rowNum = key.match(/[0-9]+/)
            sheet[key]['s'] = {
                font: {
                    sz: 14,
                    color: {
                        rgb: tB_data[rowNum[0] - 1 - th_length] && 'row_bgColor' in tB_data[rowNum[0] - 1 - th_length] ? tB_data[rowNum[0] - 1 - th_length].row_bgColor : ''
                    }
                },
                alignment: {
                    horizontal: "center",
                    vertical: "center",
                    wrapText: 1,
                    indent: 0
                }
            }
            const words = key.match(/[A-Z]+/) //获取列表中列对应得索引
            sheet[key]['t'] = tB_data[getColNum(words)]
        };
    }
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, sheet, 'table3');
    const workbook = workbook2blob(wb)
    openDownloadDialog(workbook, '导出.xlsx');
}
function getColNum(words) {
    let strArray = []
    for (let s of words) {
        if (/[A-Z]/.test(s)) strArray.push(s.charCodeAt(0) - 64)
    }
    console.log(strArray,'strArray');
}
// 将一个sheet转成最终的excel文件的blob对象，然后利用URL.createObjectURL下载
function workbook2blob(workbook) {
    // 生成excel的配置项
    var wopts = {
        // 要生成的文件类型
        bookType: "xlsx",
        // // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
        bookSST: false,
        type: "binary"
    };
    var wbout = XLSX2.write(workbook, wopts);
    // 将字符串转ArrayBuffer
    function s2ab(s) {
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
        return buf;
    }
    var blob = new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    });
    return blob;
}
/**
 * 通用的打开下载对话框方法，没有测试过具体兼容性
 * @param url 下载地址，也可以是一个blob对象，必选
 * @param saveName 保存文件名，可选
 */
function openDownloadDialog(url, saveName) {
    if (typeof url == 'object' && url instanceof Blob) {
        url = URL.createObjectURL(url); // 创建blob地址
    }
    var aLink = document.createElement('a');
    aLink.href = url;
    aLink.download = saveName || ''; // HTML5新增的属性，指定保存文件名，可以不要后缀，注意，file:///模式下不会生效
    var event;
    if (window.MouseEvent) event = new MouseEvent('click');
    else {
        event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    }
    aLink.dispatchEvent(event);
}
function getHeadProp(data) {
    return data.map(item => {
        if (item.prop) {
            return item.prop
        } else {
            return getHeadProp(item.children)
        }
    })
}
const gerMaxCol = (items) => {
    let max = 0;
    function each(data) {
        data.forEach((item) => {
            if (item.children) {
                each(item.children);
            } else {
                max = 1 + max;
            }
        });
    }
    each(items);
    return max;
}
const getMaxFloor = (treeData) => {
    let max = 0;
    function each(data, floor) {
        data.forEach((e) => {
            if (floor > max) {
                max = floor;
            }
            if (e.children && e.children.length > 0) {
                each(e.children, floor + 1);
            }
        });
    }
    each(treeData, 1);
    return max;
}
const columnsHandle = (treeData) => {
    let newArr = []

    const maxFloor = 1;
    const keyList = [];
    function each(data, index) {
        if (newArr[index] === undefined) {
            newArr[index] = [];
        }
        data.forEach((e) => {

            const obj = {
                title: e.title,
                key: e.prop,
                rowspan: maxFloor,
                colspan: 1,
                valueType: e.valueType,
                width: e.width,
            };

            if (e.children) {
                obj.colspan = gerMaxCol(e.children);
                obj.rowspan = maxFloor - getMaxFloor(e.children);
            } else {
                if (e.hasrowspan) {             //  如果存在hasrowspan属性并且值为true，则表明该key列存在跨行
                }
            }
            newArr[index].push(obj);
            if (e.children && e.children.length > 0) {
                each(e.children, index + 1);
            }
        });
        return newArr
    }
    return each(treeData, 0);
}
/**
 * @description 嵌套的数组展开平铺
 */
function flatten(arr) {
    return arr.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [])
}
/**
 * @description 创建导出的table表格html（包含图片处理）
 * @param {object[]} tHead 表头数据
 * @param {object[]} tData 表格内容数据 
 * @returns {string} 返回表格的html字符串
 */
const createTable = (tHead, tData, fileName, merge, mergeProp) => {
    let tH = '<thead >',

        tB = '', //表头和表格体
        arr = [] //表头字段集合
    // 遍历数据生成表头
    arr = getHeadProp(tHead)
    arr = flatten(arr)
    let thData = columnsHandle(tHead)
    thData.forEach((items, index) => {
        tH += `<tr style="height:100px">`
        items.forEach(item => {
            tH += `<td   width="${item.width}" valueType="${item.valueType}"  rowspan="${!item.key ? 1 : thData.length - index}" colspan="${item.colspan}">${item.title}</td>`
        })
        tH += `</tr>`

    })
    tH += '</thead >'
    let mergeSpan = {}
    if (merge) {
        mergeSpan = mergeTableRowSpan(tData, mergeProp, mergeSpan)
    }
    tData.forEach((item, index) => {
        tB += `<tr style="${arr.includes('base64') ? 'height:200px' : 'height:80px'}" >`
        arr.forEach((td, arrIndex) => {

            if (merge) {
                if (mergeSpan[td][index] > 0) {
                    tB += `<td  rowspan="${mergeSpan[td][index]}"  style="${[].includes(td) ? '' : 'mso-number-format:\\@;'}text-align:center;border:2px solid #000;font-size:14px;background-color:${item['row_bgColor']};">${(item[td] === '' || item[td] === null || item[td] === undefined) ? ' ' : item[td]}</td>`
                }
            } else {
                tB += `<td   style="${[].includes(td) ? '' : 'mso-number-format:\\@;'}text-align:center;border:2px solid #000;font-size:14px;background-color:red;">${(item[td] === '' || item[td] === null || item[td] === undefined) ? ' ' : item[td]}</td>`
            }

        })
        tB += '</tr>'

    })
    tB = '<tbody>' + tB + '</tbody>'
    if (tData.length === 0) tB = '<tbody></tbody>'
    return tH + tB

}
/*
* @param {object[]} data 导出的表格数据源
* @param {string[]} sapnArr 表格中要合并的列字段集合
* @param {[]} resArr 表格合并的row集合
* @returns 
*/
const mergeTableRowSpan = (data, sapnArr, resArr) => {
    let preKey = ''
    if (data.length === 0) return resArr
    Object.keys(data[0]).forEach((key, keyii) => {
        resArr[key] = []
        const hasIndex = sapnArr.findIndex(item => item.key === key)
        if (hasIndex > -1) {
            resArr = merge(key, preKey, keyii, data, sapnArr[hasIndex], resArr)
            preKey = key

        } else {
            resArr[key] = new Array(data.length).fill(1)
        }

    })
    return resArr
}
/**
 * 
 * @param {*} key 
 * @param {*} preKey 
 * @param {*} keyii 
 * @param {*} data 
 * @param {*} resArr
 * @param {*} obj  当前合并项
 * 
 * @returns resArr
 */
const merge = (key, preKey, keyii, data, obj, resArr) => {
    let position = 0 // 存储要合并的位置
    data.forEach((item, index) => {
        if (index === 0) {
            resArr[key].push(1)
            position = 0
        } else {
            if (obj.hasOwnProperty('reg') && obj.reg) {
                console.log(obj.reg.test(data[index][obj.regKey]), '.', obj.reg.test(data[index - 1][obj.regKey]));
                if (preKey && data[index][key] === data[index - 1][key] && resArr[preKey][index] === 0 && obj.reg.test(data[index][obj.regKey]) && obj.reg.test(data[index - 1][obj.regKey])) {
                    resArr[key][position] += 1 // 有相同项
                    resArr[key].push(0) // 名称相同后往数组里面加一项0
                } else if (!preKey && data[index][key] === data[index - 1][key] && data[index - 1][Object.keys(data[0])[keyii - 1]] === data[index][Object.keys(data[0])[keyii - 1]] && obj.reg.test(data[index][key]) && obj.reg.test(data[index - 1][key])) {
                    resArr[key][position] += 1 // 有相同项
                    resArr[key].push(0) // 名称相同后往数组里面加一项0
                }
                else {
                    resArr[key].push(1) // 同列的前后两行单元格不相同
                    position = index
                }
            } else {
                if (preKey && data[index][key] === data[index - 1][key] && resArr[preKey][index] === 0) {
                    resArr[key][position] += 1 // 有相同项
                    resArr[key].push(0) // 名称相同后往数组里面加一项0
                } else if (!preKey && data[index][key] === data[index - 1][key] && data[index - 1][Object.keys(data[0])[keyii - 1]] === data[index][Object.keys(data[0])[keyii - 1]]) {
                    resArr[key][position] += 1 // 有相同项
                    resArr[key].push(0) // 名称相同后往数组里面加一项0
                }
                else {
                    resArr[key].push(1) // 同列的前后两行单元格不相同
                    position = index
                }
            }

        }
    })
    return resArr
}
